<!DOCTYPE html>
<html>
<head>
<title>Physics Diagram of a Train and Buffer</title>
</head>
<body>

<canvas id="physicsCanvas" width="850" height="400"></canvas>

<script>
const canvas = document.getElementById('physicsCanvas');
const ctx = canvas.getContext('2d');

// --- General Settings ---
ctx.strokeStyle = 'black';
ctx.fillStyle = 'black';
ctx.lineWidth = 2;
ctx.font = '18px Arial';
ctx.textAlign = 'left';

// --- Top Text ---
const topTextY = 40;
const topTextX = 80;
let currentX = topTextX;

ctx.fillText("Fig. 3.2 shows a model train, travelling at speed", currentX, topTextY);
currentX += ctx.measureText("Fig. 3.2 shows a model train, travelling at speed ").width;

ctx.save();
ctx.font = 'italic 18px Arial';
ctx.fillText("v", currentX, topTextY);
currentX += ctx.measureText("v").width;
ctx.restore();

ctx.fillText(", approaching a buffer.", currentX, topTextY);


// --- Track ---
const trackY = 280;
ctx.beginPath();
ctx.moveTo(20, trackY);
ctx.lineTo(830, trackY);
ctx.stroke();


// --- Train ---
ctx.textAlign = 'center';
ctx.font = '20px Arial';
ctx.fillText("model train", 350, 150);

const trainY = trackY - 70;
const trainHeight = 55;
const carriageLength = 220;
const carriageGap = 10;
const wheelRadius = 8;
const wheelY = trackY - wheelRadius - 2;

// --- Rear Carriage ---
const rearCarriageX = 80;

// Chassis
ctx.fillStyle = '#d3d3d3'; // Light grey
ctx.fillRect(rearCarriageX, trainY + trainHeight, carriageLength, 15);
ctx.strokeRect(rearCarriageX, trainY + trainHeight, carriageLength, 15);

// Body
ctx.fillStyle = '#f0f0f0'; // very light grey / off-white
ctx.beginPath();
ctx.rect(rearCarriageX, trainY, carriageLength, trainHeight);
ctx.fill();
ctx.stroke();

// Grey top on rear carriage
ctx.fillStyle = '#808080'; // Grey
ctx.fillRect(rearCarriageX, trainY, carriageLength, 25);

// Windows on rear carriage
ctx.fillStyle = '#C0C0C0'; // Silver-grey
ctx.lineWidth = 1;
for (let i = 0; i < 5; i++) {
    ctx.fillRect(rearCarriageX + 25 + i * 40, trainY + 30, 30, 15);
    ctx.strokeRect(rearCarriageX + 25 + i * 40, trainY + 30, 30, 15);
}
ctx.fillRect(rearCarriageX + 25 + 5 * 40, trainY + 30, 15, 15);
ctx.strokeRect(rearCarriageX + 25 + 5 * 40, trainY + 30, 15, 15);

// Wheels on rear carriage
ctx.lineWidth = 2;
ctx.fillStyle = 'black';
// Bogie 1
ctx.fillRect(rearCarriageX + 20, wheelY - 2*wheelRadius, 50, 5);
ctx.beginPath();
ctx.arc(rearCarriageX + 35, wheelY, wheelRadius, 0, 2 * Math.PI);
ctx.arc(rearCarriageX + 55, wheelY, wheelRadius, 0, 2 * Math.PI);
ctx.fill();
// Bogie 2
ctx.fillRect(rearCarriageX + carriageLength - 70, wheelY - 2*wheelRadius, 50, 5);
ctx.beginPath();
ctx.arc(rearCarriageX + carriageLength - 55, wheelY, wheelRadius, 0, 2 * Math.PI);
ctx.arc(rearCarriageX + carriageLength - 35, wheelY, wheelRadius, 0, 2 * Math.PI);
ctx.fill();

// Coupling
ctx.fillRect(rearCarriageX + carriageLength, trainY + trainHeight + 2, carriageGap, 6);
ctx.strokeRect(rearCarriageX + carriageLength, trainY + trainHeight + 2, carriageGap, 6);

// --- Front Carriage ---
const frontCarriageX = rearCarriageX + carriageLength + carriageGap;
const frontCarriageLength = 220;
const noseLength = 30;

// Chassis
ctx.fillStyle = '#d3d3d3';
ctx.fillRect(frontCarriageX, trainY + trainHeight, frontCarriageLength, 15);
ctx.strokeRect(frontCarriageX, trainY + trainHeight, frontCarriageLength, 15);

// Body (White part)
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.moveTo(frontCarriageX, trainY);
ctx.lineTo(frontCarriageX + frontCarriageLength - noseLength/2, trainY);
ctx.quadraticCurveTo(frontCarriageX + frontCarriageLength + noseLength/2, trainY + trainHeight / 2, frontCarriageX + frontCarriageLength - noseLength/2, trainY + trainHeight);
ctx.lineTo(frontCarriageX, trainY + trainHeight);
ctx.closePath();
ctx.fill();
ctx.stroke();

// Grey pattern on front carriage
ctx.fillStyle = '#808080';
ctx.beginPath();
ctx.moveTo(frontCarriageX, trainY);
ctx.lineTo(frontCarriageX + 130, trainY);
ctx.lineTo(frontCarriageX + 90, trainY + trainHeight);
ctx.lineTo(frontCarriageX, trainY + trainHeight);
ctx.closePath();
ctx.fill();

// Windows on front carriage
ctx.lineWidth = 1;
// Door with windows
ctx.strokeRect(frontCarriageX + 150, trainY, 30, trainHeight);
ctx.fillStyle = '#C0C0C0';
ctx.fillRect(frontCarriageX + 155, trainY + 10, 20, 15);
ctx.strokeRect(frontCarriageX + 155, trainY + 10, 20, 15);
ctx.fillRect(frontCarriageX + 155, trainY + 30, 20, 15);
ctx.strokeRect(frontCarriageX + 155, trainY + 30, 20, 15);

// Driver's windows
ctx.beginPath();
ctx.moveTo(frontCarriageX + frontCarriageLength - 65, trainY + 5);
ctx.lineTo(frontCarriageX + frontCarriageLength - 35, trainY + 5);
ctx.lineTo(frontCarriageX + frontCarriageLength - 45, trainY + 25);
ctx.lineTo(frontCarriageX + frontCarriageLength - 70, trainY + 25);
ctx.closePath();
ctx.fill();
ctx.stroke();

// Wheels on front carriage
ctx.lineWidth = 2;
ctx.fillStyle = 'black';
// Bogie 1
ctx.fillRect(frontCarriageX + 20, wheelY - 2*wheelRadius, 50, 5);
ctx.beginPath();
ctx.arc(frontCarriageX + 35, wheelY, wheelRadius, 0, 2 * Math.PI);
ctx.arc(frontCarriageX + 55, wheelY, wheelRadius, 0, 2 * Math.PI);
ctx.fill();
// Bogie 2
ctx.fillRect(frontCarriageX + frontCarriageLength - 80, wheelY - 2*wheelRadius, 50, 5);
ctx.beginPath();
ctx.arc(frontCarriageX + frontCarriageLength - 65, wheelY, wheelRadius, 0, 2 * Math.PI);
ctx.arc(frontCarriageX + frontCarriageLength - 45, wheelY, wheelRadius, 0, 2 * Math.PI);
ctx.fill();

// --- Buffer ---
const bufferX = frontCarriageX + frontCarriageLength + 80;
const bufferY = trackY - 40;
const bufferWidth = 60;
const bufferHeight = 40;
const springLength = 40;

// Buffer block
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(bufferX, bufferY, bufferWidth, bufferHeight);
ctx.strokeRect(bufferX, bufferY, bufferWidth, bufferHeight);
// Supports
ctx.beginPath();
ctx.moveTo(bufferX + bufferWidth, bufferY);
ctx.lineTo(bufferX + bufferWidth + 20, trackY);
ctx.moveTo(bufferX + bufferWidth, bufferY + bufferHeight);
ctx.lineTo(bufferX + bufferWidth + 20, trackY);
ctx.stroke();

// Spring
const springX = bufferX - springLength;
const springY = bufferY + 5;
const springHeight = bufferHeight - 10;
// Spring plate
ctx.fillStyle = 'black';
ctx.fillRect(springX - 5, springY, 5, springHeight);
// Spring body
ctx.lineWidth = 1;
ctx.beginPath();
ctx.rect(springX, springY, springLength, springHeight);
ctx.stroke();
// Spring coils (using clipping)
ctx.save();
ctx.beginPath();
ctx.rect(springX, springY, springLength, springHeight);
ctx.clip();
for (let i = 2; i < springLength; i += 2) {
    ctx.beginPath();
    ctx.moveTo(springX + i, springY);
    ctx.lineTo(springX + i, springY + springHeight);
    ctx.stroke();
}
ctx.restore();

// --- Labels ---
ctx.lineWidth = 1.5;
ctx.fillStyle = 'black';
ctx.font = '20px Arial';
ctx.textAlign = 'center';

// Buffer label
ctx.fillText("buffer", bufferX + bufferWidth / 2, bufferY - 15);

// Spring Label
const springLabelX = 700;
const springLabelY = 340;
ctx.fillText("spring", springLabelX, springLabelY);
// Line for spring label
ctx.beginPath();
ctx.moveTo(springLabelX, springLabelY - 15);
ctx.lineTo(bufferX - 10, bufferY + bufferHeight);
ctx.stroke();

// Bottom Label
ctx.font = 'bold 20px Arial';
ctx.fillText("Fig. 3.2", 425, 380);

</script>

</body>
</html>